package testcase;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.NoSuchElementException;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.junit.Test;

import satir.SatirGame;
import satir.SatirTherapy;
import satir.framework.packaging.Packager.PackageExtractDestinactionWriteFailure;
import satir.framework.packaging.Packager.PackagerArchieveFileDestinationNotFoundException;
import satir.framework.packaging.Packager.PackagerArchieveFileToBeArchievedNotFoundException;
import satir.framework.packaging.Packager.PackagerArchieveZipFileWriteFailureException;
import satir.framework.packaging.Packager.PackagerExtractAchieveFileContentInvalidException;

import junit.framework.TestCase;


public class In_Lv_1_SatirTherapy_1 extends TestCase{

	private static class SatirGameStub extends SatirGame{
		
		public SatirGameStub() {
			
		}
		@Override
		public void startGame()throws PackagerExtractAchieveFileContentInvalidException,
	    PackageExtractDestinactionWriteFailure,
	    PackagerArchieveFileDestinationNotFoundException,
	    PackagerArchieveFileToBeArchievedNotFoundException,
	    PackagerArchieveZipFileWriteFailureException{
			System.out.println("Play game!");
		}
		
	}

	@Test
	public void testPlayGame(){
		 ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output here
		String input = "1\n";
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		SatirGame.getInstant(); // debug
		try {
			SatirTherapy.main(new String[] {});
		}catch (NoSuchElementException e) {
			e.printStackTrace();
		}
		System.setOut(original); // Store the output unit here
		
		String actualResult = systemOut.toString();
		String expectedResult = ("Hello\r\n" +
				"Please indicate your selection.\r\n" +
				"[1] Play game.\r\n" +
				"[2] Analyze specific user.\r\n" +
				"[3] Exit\r\n" +
				"Play game!\r\n" +
				"Please indicate your selection.\r\n" +
				"[1] Play game.\r\n" +
				"[2] Analyze specific user.\r\n" +
				"[3] Exit\r\n");

		assertEquals(expectedResult,actualResult);
				
	}

	@Aspect
	public static class TestSatirTherapyAspects {

		/**
		 * Define a Pointcut for monitoring a specific 'method call' inside a
		 * specific 'scope'
		 * 
		 * Method Call: the constructor of 'satir.SatirGame' JavaCode:
		 * SatirGame() AspectJCode: call(satir.SatirGame.new(..))
		 * 
		 * Scope: inside the method call of 'In_Lv_1_SatirTherapy_1'
		 * JavaCode: In_Lv_1_SatirTherapy_1() AspectJCode:
		 * within(In_Lv_1_SatirTherapy_1)
		 * 
		 * Explanation: This Pointcut defined that it will be triggered when the
		 * constructor of 'satir.card.Question' called inside the class of
		 * 'EventCard_doActivateCard_1_1'
		 */
		@Pointcut("call(satir.SatirGame.new(..)) && cflow(execution(void In_Lv_1_SatirTherapy_1.testPlayGame()))")
		public void interceptConstructor() {
		}

		/**
		 * Define the follow-up action after the Pointcut of
		 * 'interceptAskQuestionCmdConstructor()' has been triggered
		 * 
		 * @return SatirGame
		 * 
		 *         Explanation: After 'interceptAskQuestionCmdConstructor()' has
		 *         been triggered , the new instance of AskQuestionCmd will be
		 *         replaced by creating and returning an instance of
		 *         AskQuestionCmdStub
		 */
		@Around("interceptConstructor()")
		public SatirGame interceptConstructorForSatirGame() {
			return new SatirGameStub();
		}
	}
}
